<!--
 * @Description: 只读和浅只读
 * @Author: YWJ
 * @Date: 2025-03-24 17:14:55
 * @LastEditors: YWJ
-->
<template>
  <div></div>
</template>

<script setup>
// import { ref, reactive, toRefs, onMounted} from 'vue';
// 深响应
const reactive = (obj) => {
  return createReactive(obj);
};
// 浅响应
const shallowReactive = (obj) => {
  return createReactive(obj, true);
};
// 只读
const readonly = (obj) => {
  return createReactive(obj, false, true);
};
// 浅只读
const shallowReadonly = (obj) => {
  return createReactive(obj, true, true);
};
const createReactive = (obj, isShallow = false, isReadonly = false) => {
  return new Proxy(obj, {
    // 拦截读取操作
    get(target, key, receiver) {
      if (key === "raw") {
        return target;
      }
      // 非只读的时候才需要建立响应联系
      if (!isReadonly) {
        track(target, key);
      }
      // 得到原始值结果
      const res = Reflect.get(target, key, receiver);
      if (isShallow) {
        return res;
      }
      if (typeof res === "object" && res !== null) {
        // 如果数据为只读，则调用 readonly 对值进行包装
        return isReadonly ? readonly(res) : reactive(res);
      }
      return res;
    },
    set(target, key, newVal, receiver) {
      // 如果是只读的，则打印警告信息并返回
      if (isReadonly) {
        console.warn(`属性 ${key} 是只读的`);
        return true;
      }
      const oldVal = target[key];
      const type = Object.prototype.hasOwnProperty.call(target, key)
        ? "SET"
        : "ADD";
      const res = Reflect.set(target, key, newVal, receiver);
      if (target === receiver.raw) {
        if (oldVal !== newVal && (oldVal === oldVal || newVal === newVal)) {
          trigger(target, key, type);
        }
      }

      return res;
    },
    deleteProperty(target, key) {
      // 如果是只读的，则打印警告信息并返回
      if (isReadonly) {
        console.warn(`属性 ${key} 是只读的`);
        `123456/789`;
        return true;
      }
      const hadKey = Object.prototype.hasOwnProperty.call(target, key);
      const res = Reflect.deleteProperty(target, key);

      if (res && hadKey) {
        trigger(target, key, "DELETE");
      }

      return res;
    },
    // 省略其他拦截函数
  });
};
</script>
<style lang="scss" scoped></style>
